#include "PTCamera.h"


PTCamera::PTCamera() {

	bIsActive = false;
	CoInitialize(NULL);
}


PTCamera::~PTCamera() {

	this->Release();
	CoUninitialize();
}


bool PTCamera::Init() {

	ICreateDevEnum *pCreateDevEnum = NULL;
	CoCreateInstance( CLSID_SystemDeviceEnum, 
					  NULL, 
					  CLSCTX_INPROC_SERVER, 
					  IID_ICreateDevEnum, 
					  (PVOID*)&pCreateDevEnum );

	IEnumMoniker *pEnumMoniker = NULL;
	pCreateDevEnum->CreateClassEnumerator( CLSID_VideoInputDeviceCategory, 
										   &pEnumMoniker,
										   0 );

	if ( pEnumMoniker == NULL ) {
	
		perror( "ERROR: No video input devices found...\n" );
		return false;
	} else {
		
		IMoniker *pMoniker = NULL;
		ULONG nFetched = 0;

		if ( pEnumMoniker->Next( 1, &pMoniker, &nFetched ) == S_OK ) {
		
			IPropertyBag *pPB = NULL;
			
			pMoniker->BindToStorage( 0, 
									 0, 
									 IID_IPropertyBag, 
									 (void**)&pPB );

			VARIANT v;
			v.vt = VT_BSTR;
			pPB->Read( L"FriendlyName", &v, 0 );
			WideCharToMultiByte( CP_ACP,
								 0,
								 v.bstrVal, 
								 -1, 
								 (LPSTR)sDevName, 
								 sizeof(sDevName), 
								 0, 
								 0 );
			VariantClear(&v);
			pMoniker->BindToObject( 0,
									0,
									IID_IBaseFilter,
									(void**)&pDeviceFilter );

			pMoniker->Release();
			pPB->Release();

			if (pDeviceFilter != NULL ) {
			
				return true;
			} else {
			
				perror( "ERROR: Device filter not properly bound...\n" );
				return false;
			}
		} else {
		
			perror( "ERROR: No devices found...\n" );
			return false;
		}
	}
}


bool PTCamera::Run() {

	if ( pDeviceFilter != NULL ) {
	
		CoCreateInstance( CLSID_FilterGraph,
						  NULL,
						  CLSCTX_INPROC,
						  IID_IGraphBuilder,
						  (LPVOID *)&pGraphBuilder );

		CoCreateInstance( CLSID_CaptureGraphBuilder2,
						  NULL,
						  CLSCTX_INPROC,
						  IID_ICaptureGraphBuilder2,
						  (LPVOID*)&pCaptureGraphBuilder );

		pCaptureGraphBuilder->SetFiltergraph( pGraphBuilder );
		pGraphBuilder->QueryInterface( IID_IMediaControl,
									   (LPVOID*)&pMediaControl );

		pGraphBuilder->AddFilter( pDeviceFilter, L"Device Filter" );
		pCaptureGraphBuilder->RenderStream( &PIN_CATEGORY_PREVIEW,
											NULL,
											pDeviceFilter,
											NULL,
											NULL );
		bIsActive = true;
		pMediaControl->Run();

		return true;
	} else {
	
		perror( "ERROR: Camera has not been initialized ( see PTCamera::Init()... )\n" );
		return false;
	}
}


bool PTCamera::Pause() {

	if ( pDeviceFilter != NULL ) {
	
		pMediaControl->Pause();

		return true;
	} else {
	
		perror( "ERROR: Camera has not been initialized ( see PTCamera::Init()... )\n" );
		return false;
	}
}


bool PTCamera::Stop() {

	if ( pDeviceFilter != NULL ) {
	
		pMediaControl->StopWhenReady();
		bIsActive = false;

		return true;
	} else {
	
		perror( "ERROR: Camera is not currently running...\n" );
		return false;
	}
}


bool PTCamera::Capture( PTBitmap &bmp ) {

	return false;
}


void PTCamera::Release() {

	if ( pDeviceFilter != NULL ) {
	
		bIsActive = false;

		pMediaControl->Stop();
		pMediaControl->Release();

		pCaptureGraphBuilder->Release();
		pGraphBuilder->Release();

		pDeviceFilter->Release();

	} else {
	
		perror( "ERROR: Camera has not been released, as it doesn't exist...\n" );
	}
}